package NajaTaskClient.Conexao;

import java.util.Vector;

/*
 * Elementos que compoem uma tabela de um banco de dados . Usado para facilitar
 * a implementação do sistema de catalogo
 */
/**
 *
 * @author NidorX
 */
public class DbTabelaColuna implements Comparable<DbTabelaColuna> {
    /*
    nome_coluna tipo [NOT NULL | NULL] [AUTO_INCREMENT]
    tipo
    |    INT[(tamanho)]
    |    FLOAT[(tamanho,decimais)]
    |    DECIMAL(tamanho,decimais)
    |    VARCHAR(tamanho)
    |    DATE
    |    TIME
    |    TEXT
    |    LONGTEXT
     */

    String[] tipos = {"INT", "FLOAT", "DECIMAL", "VARCHAR", "TEXT", "LONGTEXT", "DATE", "TIME"};
    String nome;
    String tipo;
    int tamanho;
    boolean nulo;
    boolean autoIncrementa; //
    boolean primaria;
    private DbTabela tabelaPai;

    /**
     *
     * @param nome
     * @param tipo
     * @param tamanho
     * @param nulo
     * @param autoIncrementa
     * @param primaria
     */
    public DbTabelaColuna(String nome, String tipo, int tamanho, boolean nulo, boolean autoIncrementa, boolean primaria) {
        this.nome = nome;
        this.tipo = tipo;
        this.tamanho = tamanho;
        this.nulo = nulo;
        this.autoIncrementa = autoIncrementa;
        this.primaria = primaria;
        try {
            this.testaDados();
        } catch (ExcecaoGenericaMensagem ex) {
            //ex.printStackTrace();
        }
    }

    public int compareTo(DbTabelaColuna o) {
        final int EQUAL = 0;
        final int AFTER = 1;

        if (this == o) {
            return EQUAL;
        }
        if (this.nome.equals(o.nome)) {

            return EQUAL;
        }

        return AFTER;
        // throw new UnsupportedOperationException("Not supported yet.");
    }

    /**
     * Obtem o nome da coluna atual
     * @return String colunaNome
     */
    public String obterNome() {
        return this.nome;
    }

    /**
     *
     * @return
     */
    public String obterTipo() {
        return this.tipo;
    }

    /**
     *
     * @return
     */
    public int obterTamanho() {
        return this.tamanho;
    }

    /**
     * 
     * @return
     */
    public boolean obterChavePrimaria() {
        return this.primaria;
    }

    /**
     *
     * @return
     */
    public boolean obterNulo() {
        return this.nulo;
    }

    /**
     *
     * @return
     */
    public boolean obterAutoIncrementa() {
        return this.autoIncrementa;
    }

    /**
     * define um novo tamanho para essa coluna .
     * @param tamanho
     */
    public void setarTamanho(int tamanho) {
        this.tamanho = tamanho;
    }

    /**
     * Testa os dados 
     * @throws ExcecaoGenericaMensagem
     */
    public void testaDados() throws ExcecaoGenericaMensagem {
        // 1º testar se o tipo está certo
        boolean certo = false;
        for (String t : this.tipos) {
            if (t.equals(this.tipo)) {
                certo = true;
                break;
            }
        }
        if (!certo) {
            String tiposSuportados = "";
            if (this.tipos.length > 0) {
                tiposSuportados = this.tipos[0];    // start with the first element
                for (int i = 1; i < this.tipos.length; i++) {
                    tiposSuportados = tiposSuportados + " , " + this.tipos[i];
                }
            }
            throw new ExcecaoGenericaMensagem("Tipo de coluna \"" + this.tipo + " \"Nao suportado.\n"
                    + "Os tipos suportados sao : \n" + tiposSuportados + "\nPor padrão , os tipos sao CaseSense.");
        } //2º para cada tipo testar os requisitos segundo o tipo de coluna
        else {
            // se precisam de tamanho definido
            if (this.tipo.equals("INT") || this.tipo.equals("DECIMAL") || this.tipo.equals("VARCHAR")) {
                if (this.tamanho <= 0) {
                    throw new ExcecaoGenericaMensagem("Tamanho deve ser um valor maior que 0(zero) para esse tipo de Coluna : " + this.tipo);
                }

            }
            // se podem ser chaves primarias
            if (this.tipo.equals("VARCHAR") || this.tipo.equals("TEXT") || this.tipo.equals("LONGTEXT")) {
                if (this.primaria) {
                    throw new ExcecaoGenericaMensagem("Esse tipo de coluna \"" + this.tipo + "\" nao pode ser Chave Primaria ");
                }
            }
            // se podem ser auto increment
            if (this.tipo.equals("INT") || this.tipo.equals("FLOAT") || this.tipo.equals("DECIMAL")) {
                if (this.autoIncrementa || this.primaria) {

                    if ((!this.primaria && this.autoIncrementa)) {
                        throw new ExcecaoGenericaMensagem("Uma coluna só pode ser AUTO_INCREMENT se for PRIMARY");
                    }
                    if ((this.primaria && !this.autoIncrementa)) {
                        this.autoIncrementa = true;
                    }

                }
            } else {
                this.autoIncrementa = false;
            }
        }


    }

    /**
     * Obtem o nome da coluna atual
     * @return String colunaNome
     */
    public String obterStringSql() {
        String sql = this.nome + " " + this.tipo;
        if (this.tipo.equals("INT") || this.tipo.equals("FLOAT") || this.tipo.equals("DECIMAL") || this.tipo.equals("VARCHAR")) {
            sql += "(" + this.tamanho + ") ";
            // tabela INT(11)

            if (this.nulo) {
                sql += " NULL ";
            } else {
                sql += " NOT NULL ";
            }

            if (this.autoIncrementa) {
                sql += " AUTO_INCREMENT PRIMARY KEY";
            }
            // tabela INT(11) AUTO_INCREMENT PRIMARY
        } else {
            if (this.nulo) {
                sql += " NULL ";
            } else {
                sql += " NOT NULL ";
            }
            // tabela
        }
        return sql;
    }

    /**
     *
     */
    public void exibeDados() {
        System.out.println("{\n"
                + "\tNome: " + this.nome + "\n"
                + "\tTipo: " + this.tipo + "\n"
                + "\tTamanho: " + this.tamanho + "\n"
                + "\tNulo ?: " + this.nulo + "\n"
                + "\tAutoincrementa ?: " + this.autoIncrementa + "\n"
                + "\tPrimária ?: " + this.primaria
                + "\n}");
    }

    /**
     *
     * @param args
     */
    public static void main(String[] args) {

        DbTabelaColuna col = new DbTabelaColuna("nome", "INT", 100, true, false, false);
        System.out.println(col.obterStringSql());
    }

    /**
     * Verifica no banco de dados se uma coluna com esse valor já está inserido
     * @param valor
     * @return
     */
    public boolean inserido(String valor) {
      
        if (Db.get().dbTabelaColunaExisteValor(this.tabelaPai.obterNome(), this.obterNome(), valor)) {
            return true;
        }
        return false;
    }

    

    /**
     * retorna o valor do campo da coluna atual no banco de dados para o
     * argumento estabelecido exempo codigo=2 ou nome=alex
     * @param argumento

     * @return
     */
    public Vector<String> where(String argumento) {
        return Db.get().dbTabelaColunaObterValor(this.tabelaPai.obterNome(), this.obterNome(), argumento);
        //return "";
    }

    /**
     * diz para esse objeto em qual tabela ela está contida . Ultilizado para algumas
     * consultas
     * @param tabPai
     */
    void setarTabela(DbTabela tabPai) {
        this.tabelaPai = tabPai;
    }
}
